using System;
using CommunityToolkit.Mvvm.ComponentModel;
using mas.Models;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using CommunityToolkit.Mvvm.Input;
using ScottPlot;
using ScottPlot.Plottables;

namespace mas.ViewModels;

public partial class PlotWindowViewModel : ObservableObject
{
    private readonly UdpService _udpService;
    
    // 数据记录器（ViewModel 管理）
    public DataLogger Logger { get; private set; }

    // 公开HeaderDatas供View访问
    public ObservableCollection<HeaderData> HeaderDatas => _udpService.HeaderDatas;
    // 控制图表是否处于暂停状态
    [ObservableProperty]
    private bool _isPaused = false;
    
    // 用于支持多个数据通道
    public ObservableCollection<PlotChannel> PlotChannels { get; } = new ();
    
    // 暂停/恢复图表更新命令
    [RelayCommand]
    private void TogglePause()
    {
        IsPaused = !IsPaused;
    }

    public PlotWindowViewModel(UdpService udpService)
    {
        _udpService = udpService;
        Logger = new DataLogger();  // 创建DataLogger实例
        
        // 初始化5个数据通道
        for (int i = 0; i < 5; i++)
        {
            var channel = new PlotChannel(i + 1, udpService);
            PlotChannels.Add(channel);
        }
    }
}

// 表示一个数据通道的类
public partial class PlotChannel : ObservableObject
{
    private readonly UdpService _udpService;
    private HeaderData? _previousSelectedHeader;
    
    public int ChannelNumber { get; }
    public DataLogger Logger { get; }
    
    [ObservableProperty]
    private HeaderData? _selectedHeader;
    
    [ObservableProperty]
    private string? _selectedJsonField;
    
    public ObservableCollection<string> JsonFields { get; } = new ();
    
    public ObservableCollection<HeaderData> HeaderDatas { get; }
    
    public string ChannelInfo => SelectedHeader != null && !string.IsNullOrEmpty(SelectedJsonField) 
        ? $"{SelectedHeader.Header}::{SelectedJsonField}" 
        : $"Channel {ChannelNumber}";

    public PlotChannel(int channelNumber, UdpService udpService)
    {
        ChannelNumber = channelNumber;
        Logger = new DataLogger();
        _udpService = udpService;
        HeaderDatas = udpService.HeaderDatas;
        
        PropertyChanged += (s, e) =>
        {
            if (e.PropertyName == nameof(SelectedHeader))
            {
                UpdateJsonFields();
                UpdateMessageSubscription();
            }
            else if (e.PropertyName == nameof(SelectedJsonField))
            {
                Logger.Clear();
                OnPropertyChanged(nameof(ChannelInfo));
            }
        };
    }
    
    private void UpdateMessageSubscription()
    {
        if (_previousSelectedHeader != null)
        {
            _previousSelectedHeader.PropertyChanged -= SelectedHeader_PropertyChanged;
        }

        if (SelectedHeader != null)
        {
            SelectedHeader.PropertyChanged += SelectedHeader_PropertyChanged;
        }

        _previousSelectedHeader = SelectedHeader;
    }
    
    private void SelectedHeader_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        if (e.PropertyName == nameof(HeaderData.Message) && 
            SelectedHeader != null && 
            !string.IsNullOrEmpty(SelectedJsonField))
        {
            ProcessData();
        }
    }
    
    private void UpdateJsonFields()
    {
        JsonFields.Clear();
        
        if (SelectedHeader != null)
        {
            List<string> fields = _udpService.GetJsonFieldsForHeader(SelectedHeader.Header);
            foreach (var field in fields)
            {
                JsonFields.Add(field);
            }
        }
        
        OnPropertyChanged(nameof(ChannelInfo));
    }
    
    private void ProcessData()
    {
        if (SelectedHeader == null || string.IsNullOrEmpty(SelectedJsonField))
            return;
            
        string? rawJsonValue = GetJsonFieldRawValue(SelectedHeader.Message, SelectedJsonField);
        
        if (double.TryParse(rawJsonValue, out double numericValue))
        {
            double relativeTimeMs = DateTime.Now.TimeOfDay.TotalMilliseconds;
            Logger.Add(relativeTimeMs, numericValue);
        }
    }
    
    private string? GetJsonFieldRawValue(string json, string fieldPath)
    {
        try
        {
            if (string.IsNullOrEmpty(json) || string.IsNullOrEmpty(fieldPath))
                return null;

            using var doc = JsonDocument.Parse(json);
            var element = doc.RootElement;
            
            foreach (var segment in fieldPath.Split('.'))
            {
                if (!element.TryGetProperty(segment, out var child))
                    return null;
                element = child;
            }

            string rawValue = element.GetRawText();
            if (rawValue.StartsWith("\"") && rawValue.EndsWith("\""))
            {
                rawValue = rawValue.Trim('"');
            }
            return rawValue;
        }
        catch
        {
            return null;
        }
    }
}
